package com.shenhangye.pushlive.gles

import android.graphics.Bitmap
import android.opengl.EGL14
import android.opengl.EGLSurface
import android.opengl.GLES30
import android.util.Log
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileOutputStream
import java.nio.ByteBuffer
import java.nio.ByteOrder

open class EglSurfaceBase {
    private  val TAG = "EglSurfaceBase"

    protected var mEglCore:EglCore?=null

    private var mEGLSurface:EGLSurface?=EGL14.EGL_NO_SURFACE;
    private var mWidth = -1
    private var mHeight = -1


    constructor(eglCore: EglCore){
        this.mEglCore=eglCore;
    }
    /**
     * Creates a window surface.
     * <p>
     * @param surface May be a Surface or SurfaceTexture.
     */
    fun createWindowSurface(surface: Any){
        if (mEGLSurface!=EGL14.EGL_NO_SURFACE){
            throw IllegalStateException("surface already created")
        }
        mEGLSurface=mEglCore?.createWindowSurface(surface)
    }
    /**
     * Creates an off-screen surface.
     */

    fun createOffscreenSurface(widhth:Int,height:Int){

        mEGLSurface=mEglCore?.createOffScreenSurface(widhth,height);
        mWidth=widhth;
        mHeight=height;
    }
    /**
     * Returns the surface's width, in pixels.
     * <p>
     * If this is called on a window surface, and the underlying surface is in the process
     * of changing size, we may not see the new size right away (e.g. in the "surfaceChanged"
     * callback).  The size should match after the next buffer swap.
     */

    fun getWidth(): Int {
        return if (mWidth<0){
            mEglCore!!.querySurface(mEGLSurface,EGL14.EGL_WIDTH);
        }else{
            mWidth;
        }
    }

    /**
     * Returns the surface's height, in pixels.
     */
    fun getHeight(): Int {
        return if (mHeight < 0) {
            mEglCore!!.querySurface(mEGLSurface, EGL14.EGL_HEIGHT)
        } else {
            mHeight
        }
    }


    /**
     * Release the EGL surface.
     */
    fun releaseEglSurface() {
        mEglCore?.releaseSurface(mEGLSurface)
        mEGLSurface = EGL14.EGL_NO_SURFACE
        mHeight = -1
        mWidth = mHeight
    }
    /**
     * Makes our EGL context and surface current.
     */
    public fun makeCurrent(){
        mEGLSurface?.let { mEglCore?.makeCurrent(it) }
    }
    /**
     * Makes our EGL context and surface current for drawing, using the supplied surface
     * for reading.
     */

    fun makeCurrentReadForm(readSurface:EglSurfaceBase ){
        mEglCore?.makeCurrent(mEGLSurface, readSurface.mEGLSurface)
    }



    fun swapBuffers():Boolean?{
        var result= mEGLSurface?.let { mEglCore?.swapBuffers(it) };
        return result;
    }
    /**
     * Sends the presentation time stamp to EGL.
     *
     * @param nsecs Timestamp, in nanoseconds.
     */
    fun setPresentationTime(nsecs:Long){
        mEglCore?.setPresentationTime(mEGLSurface,nsecs);
    }

    fun saveFrame(file: File){
        if (mEglCore?.isCurrent(mEGLSurface!!) == false) {

        }


        var filename=file.toString()

        var width=getWidth();
        var height=getHeight()

        var buf=ByteBuffer.allocateDirect((width?.times(height) ?: 0) *4)
        buf.order(ByteOrder.LITTLE_ENDIAN)
        GLES30.glReadPixels(0,0,width,height,GLES30.GL_RGBA,GLES30.GL_UNSIGNED_BYTE,buf)
        buf.rewind();

        var bos:BufferedOutputStream?=null
        try {
            bos = BufferedOutputStream(FileOutputStream(filename))
            val bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
            bmp.copyPixelsFromBuffer(buf)
            bmp.compress(Bitmap.CompressFormat.PNG, 90, bos)
            bmp.recycle()
        } finally {
            bos?.close()
        }
        Log.d(TAG, "Saved " + width + "x" + height + " frame as '" + filename + "'")



    }





}